//FRAMS (framework management system)
//part of the AXL (allegro XML based library) project
//by neil walker 2005
#ifndef axl_framework
#define axl_framework

#include "axl.h"
#include "axl_config.h"
#include "axl_animations.h"

namespace AXL_Projects {
	//timer routines and variables
	//a bit scared to put them as class methods/data just in case
	//there is something wrong with timers and classes
	void TimerDigiPurgeNow(void);
	void TimerFpsHandler(void);		//for monitoring the fps
	void TimerGameTimer(void);		//speed controller
	
	enum TimerType {GAME_INTRO=0, GAME_MENU, GAME_GAME, GAME_EXIT};	
	class Framework
	{
//public methods
	public:
		//constructors. before anything is called the end of the constructor should be an allegro mode
		//1. initialise using config xml file and optional animation file
		//2. initialise using config parameters as manual config constructor and optional animation file
		//   pass in "" to signify no animation. no default as would end up with ambiguous constructors
		Framework(const std::string& configfilename, const std::string& animationfilename, bool initialiseSystem=true,BITMAP* (*bitmapcreator)(const std::string&)=NULL);
		~Framework();
		void InitialiseFramework();		//called by constructors
								//if auto initialise is not being called in constructor, call it here
								//useful if you want to override some XML config settings, e.g. width/height
		
		//initialise frameloop and start game
		//return true from any function to signify end of game loop
		bool StartGameLoop(		
								bool (*logiclogo)(void),
								bool (*drawinglogo)(void),
								bool (*logicmenu)(void),
								bool (*drawingmenu)(void),
								bool (*logicgame)(void),
								bool (*drawinggame)(void),
								bool (*logicexit)(void),
								bool (*drawingexit)(void),
								bool bUseEscToExit=true
							);
		void DestroyFramework(bool called_from_destructor=false);
		//instead of using lots of conditional statements in each logic/drawing above
		//call this as an override and inside the main loop the functions passed in
		//will be called again, returning true to signify removing override and 
		//continuing on using the normal hooks
		void SetAutoGameLoopOverride(
								bool (*logic)(void),
								bool (*drawing)(void)
								);
		void ChangeTimerType(TimerType activeTimerType);

		bool RestartSystem(void);	//restart everything
		
		//use methods to make game use its own variables
		Configuration* GetConfiguration() {return GameConfiguration;}
		AnimationLibrary* GetGraphicsLibrary() { return GameAnimationLibrary ;}
		BITMAP** GetGraphicBuffers() { return BitmapPages;}

		//system
		void AbortSystem(const std::string& err);
		bool DatLoad(DATAFILE** dat, const std::string& file, bool stop);
		void MsgBox(const char* msg1,const char* msg2,BITMAP* bmp=screen,int waitforkey=KEY_SPACE);
		void MsgBox(const char* line1,const char* line2, BITMAP* bmp, int w,int h,int transcolour, int forecolour, bool transparent,int waitforkey=0);
		void WaitForKey(int keyp=KEY_SPACE);
		//sound/midi
		void SoundPlayMidi(MIDI* tune, bool loopflag=false,int vol=-1);
		void SoundStopMidi();
		int SoundPlayDigi(DATAFILE* df, int samplenum,int vol=-1, int loopflag=false);
		int SoundPlayDigi(SAMPLE* samp, int vol=-1, int loopflag=false);
		void SoundStopDigi(int voice,bool force);
		void SoundPurgeDigi(bool killit=false);
		void SoundKillDigi();
		int SoundDigiPos(int voice);
		void SoundSetStandardVolumeDigi(int val) 
		{
			if(val>=0 && val<=255)
				GameConfiguration->CapsSound.SampleVolume=val;
		}
		void SoundSetStandardVolumeMusic(int val)
		{
			if(val>=0 && val<=255)
				GameConfiguration->CapsSound.MusicVolume=val;
		}
		
//public data
	public:						
		BITMAP* DrawingSurface;		//the bitmap the user can draw on whether double, triple or paged is being used
									//other drawing surfaces are private as not required to be exposed	
									//pointer to BitmapPages[BitmapPagesActive]
	
	private:
//private methods
		bool InitialiseSubSystem();		//framework adds extra stuff like videobuffers, etc. called by InitialiseFramework()
		void GameLoop(			//actual loop - called by startgameloop
						bool (*logiclogo)(void),
						bool (*drawinglogo)(void),
						bool (*logicmenu)(void),
						bool (*drawingmenu)(void),
						bool (*logicgame)(void),
						bool (*drawinggame)(void),
						bool (*logicexit)(void),
						bool (*drawingexit)(void),
						bool bUseEscToExit
						);
//private data
	private:		
		//game loop functions and variables
		Configuration* GameConfiguration;
		AnimationLibrary* GameAnimationLibrary;
		TimerType ActiveTimerType;

		bool ActiveTimerSwitch;

		//the game loops and timers are not in class as are needed by timer routines
		BITMAP* BitmapPages[3];		//double buffers only use 0
									//paging uses 0,1
									//triple uses 0,1,2
		unsigned int BitmapPagesActive;	//current drawing surface to write to
		bool TimersActive;			//whether timers have been started
		bool DigiPurgeActive;		//whether digi purge timer has been started
		
		//frame loop stuff
		bool AutoOverride;			//if we have a loop override function
		bool (*AutoLogic)(void);	//the loop override functions
		bool (*AutoDraw)(void);
		
		int fps;
		int VoiceArray[255];		//maximum allowed voices
		std::string AnimationFile;	//for restarting system
		BITMAP* (*BitmapCreator)(const std::string& bmpname);
	};
}

#endif
